// The MIT License

// Copyright (c) 2009 Massachusetts Institute of Technology

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Connectable::*;
import GetPut::*;
import ClientServer::*;
import FIFOF::*;
import FIFO::*;

// Local includes
`include "asim/provides/processor_library.bsh"

interface MemArb;

// wjun
  interface Server#(MainMemReq,MainMemResp) imem_server;
  //interface Server#(InstReq,InstResp) imem_server;
  interface Client#(MainMemReq,MainMemResp) imem_client;
endinterface

//typedef enum { REQ0, REQ1 } ReqPtr deriving(Eq,Bits);

module mkMemArb( MemArb );

  //-----------------------------------------------------------
  // State

  // wjun - Qs for instruction fetching
  FIFO#(MainMemReq)  mireqQ  <- mkBFIFO1();
  FIFO#(MainMemResp) mirespQ <- mkBFIFO1();
  FIFO#(MainMemReq)  ireqQ  <- mkBFIFO1();
  FIFO#(MainMemResp) irespQ <- mkBFIFO1();
//  FIFO#(InstReq)  ireqQ  <- mkBFIFO1();
//  FIFO#(InstResp) irespQ <- mkBFIFO1();

//  Reg#(ReqPtr) nextReq <- mkReg(REQ0);

  //-----------------------------------------------------------
  // Rules

  // wjun
  rule instrReq;
		//$display("ireqQ");
		MainMemReq mreq = ireqQ.first();
/*		MainMemReq mreq
     = case ( ireqQ.first() ) matches
         tagged LoadReq  .ld : return LoadReq { tag:1, addr:ld.addr };
	 			tagged StoreReq .st : return ?;// ireqQ.first();
       endcase;
*/
		mireqQ.enq(mreq); 
  	ireqQ.deq();
  endrule

  rule returnInstResp;
		//$display("irespQ");
 /*   let tag 
     = case ( mirespQ.first() ) matches
	 tagged LoadResp  .ld : return ld.tag;
	 tagged StoreResp .st : return ?;
       endcase;
*/
  	mirespQ.deq();
		irespQ.enq(mirespQ.first());
  endrule
  //-----------------------------------------------------------
  // Methods
  
	// wjun - Qs for instruction fetching
  interface Server imem_server;
    interface Get request  = fifoToPut(ireqQ);
    interface Put response = fifoToGet(irespQ);
  endinterface
  
  interface Client imem_client;
    interface Get request  = fifoToGet(mireqQ);
    interface Put response = fifoToPut(mirespQ);
  endinterface

endmodule


